use crc32fast::hash;
use prost::{bytes::{BufMut, BytesMut}, length_delimiter_len};

#[derive(PartialEq, Eq)]
pub enum LogRecordType {
    NORMAL = 1,

    DELETED = 2,
}

impl LogRecordType {
    pub fn from_u8(v:u8) -> Self {
        match v {
            1 => LogRecordType::NORMAL,
            2 => LogRecordType::DELETED,
            _ => panic!("log record type err")
        }
    }

}


pub struct LogRecord {
    pub(crate) key: Vec<u8>,
    pub(crate) value: Vec<u8>,
    pub(crate) rec_type: LogRecordType,
}

impl LogRecord {

    pub fn encode(&self)-> Vec<u8> {
        let (data,_) = self.encode_and_get_crc();
        
        data
    }

    pub fn encode_and_get_crc(&self) -> (Vec<u8>,u32) {
        
        let mut data = BytesMut::new();
        data.reserve(self.encoded_length());

        // type值 u8
        let record_type = match &self.rec_type {
            LogRecordType::DELETED => 2u8,
            LogRecordType::NORMAL => 1u8,
        };
        data.put_u8(record_type);

        // key大小 u32  value u64 
        let key_size = self.key.len() as u32;
        let value_size = self.value.len() as u64;
        data.put_u32(key_size);
        data.put_u64(value_size);
        
        // key 及 value
        data.extend_from_slice(&self.key);
        data.extend_from_slice(&self.value);
        
        //计算crc
        let mut hasher = crc32fast::Hasher::new();
        hasher.update(&data);
        let crc = hasher.finalize();
        data.put_u32(crc);
        
        (data.to_vec(),crc)

    }

    // logrecord 编码后长度
    fn encoded_length(&self) -> usize {
        let len = self.key.len() + self.value.len() + 13 + 4;
        len
    }

    pub fn get_crc(&self)->u32 {
        let (_,crc) = self.encode_and_get_crc();   
        crc
    }


}

#[derive(Copy, Debug, Clone)]
pub struct LogRecordPos {
    pub(crate) file_id: u32,
    pub(crate) offset: u64,
}


pub struct ReadLogRecord {
    pub(crate) record:LogRecord,
    pub(crate) size:u64,
}